<template>
    <div class="bottomContent">
        <div class="functions">
            <el-tooltip content="发送语音" effect="customized">
                <div class="function">
                    <Voice></Voice>
                </div>
            </el-tooltip>
            <el-tooltip content="选择文件" effect="customized">
                <div class="function">
                    <sendFile></sendFile>
                </div>
            </el-tooltip>
            <el-tooltip content="语音通话" effect="customized">
                <div class="function" @click="beginAudio">
                    <SvgIcon name="audio-call" width="1.8rem" height="1.8rem"></SvgIcon>
                </div>
            </el-tooltip>
            <el-tooltip content="视频通话" effect="customized">
                <div class="function" @click="beginVideo">
                    <SvgIcon name="video-call" width="1.8rem" height="1.8rem"></SvgIcon>
                </div>
            </el-tooltip>
        </div>
        <div class="messageInput" contenteditable @paste="handlePaste" ref="messageInput"></div>
        <div class="buttonContainer">
            <el-button type="primary" size="default" @click="sendMessage()" class="send">
                发送
            </el-button>
        </div>
    </div>
</template>

<script setup lang="ts">
import { reactive, ref, watch } from 'vue'
import useUserStore from '@/store/modules/user'
import useMessagesStore from '@/store/modules/messages'
import type { messageFormData } from '@/api/messages/type'
import { useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import { save } from '@/utils/savemessage'
import { base64ToFile, calcFileSize, getImageDimensions, saveFile } from '@/utils/chatfile'
import useWebSocketStore from '@/store/modules/wschat'
import { FileData } from '@/api/file/type'

const $route = useRoute()
const userStore = useUserStore()
const messageStore = useMessagesStore()
const webSocketStore = useWebSocketStore()
//聊天消息http请求体定义
let reqmessage = reactive<messageFormData>({
    message_type: '',
    conversation_id: -1,
    sender_id: userStore.userId,
    receiver_id: -1,
    message_content: '',
    send_time: 0,
    media: null,
    media_url: null,
    media_size: '',
    file_width: 0,
    file_height: 0,
})
const messageInput = ref<HTMLTextAreaElement | null>(null)
// 粘贴的文件的数据
const parseData = reactive<FileData>({
    fileId: '',
    previewUrl: '',
    fileWidth: 0,
    fileHeight: 0,
    fileType: 'picture',
    fileData: '',
    fileName: '',
    fileSize: '',
})

const beginVideo = () => {
    webSocketStore.callType = 'video'
    webSocketStore.callTo = true
}

const beginAudio = () => {
    webSocketStore.callType = 'audio'
    webSocketStore.callTo = true
}

const handlePaste = (event: ClipboardEvent) => {
    // 检查是否有文件被粘贴
    if (event.clipboardData && event.clipboardData.files.length > 0) {
        event.preventDefault() // 阻止默认粘贴行为

        const file = event.clipboardData.files[0] // 获取粘贴的文件
        parseData.fileName = file.name
        parseData.fileSize = calcFileSize(file.size)

        if (file.type.startsWith('image/')) {
            // 检查文件是否为图片
            const reader = new FileReader() // 创建 FileReader 对象

            reader.onload = async (e) => {
                const imgData = await getImageDimensions(e.target!.result as string)
                parseData.fileWidth = imgData.width
                parseData.fileHeight = imgData.height
                imgData.image.src = e.target!.result as string
                imgData.image.style.maxWidth = '100px' // 设置图片的宽度
                imgData.image.style.maxHeight = '100px' // 设置图片的高度
                imgData.image.setAttribute('parseData', JSON.stringify(parseData))

                // 将图片插入到输入框中
                messageInput.value?.appendChild(imgData.image)
            }

            reader.readAsDataURL(file) // 读取文件内容
        } else {
            ElMessage({
                type: 'warning',
                message: '仅支持粘贴图片文件',
            })
        }
    }
}

// 解析富文本消息发送框里面的内容
const parseRichText = (element: HTMLElement) => {
    const text = element.textContent || '' // 提取纯文本内容

    // 提取所有图片
    const images: FileData[] = []
    const imgElements = element.querySelectorAll('img')
    imgElements.forEach((img) => {
        const imgData: FileData = JSON.parse(img.getAttribute('parseData') as string)
        imgData.fileData = img.src
        images.push(imgData)
    })

    return {
        text,
        images,
    }
}

// 实时通讯
const handleFile = async (file?: Blob, fileName?: string) => {
    if (webSocketStore.isConnected) {
        if (file && fileName) {
            //将文件保存到本地
            await saveFile(reqmessage.message_type, file, fileName)
        }
        await messageStore.sendMessage(reqmessage)
        webSocketStore.sendMessage(reqmessage)
        //发送成功将消息存到本地和仓库中
        messageStore.conversations = save(messageStore.conversations, reqmessage)
    } else {
        return ElMessage({
            type: 'error',
            message: '网络未连接，请检查网络状态',
        })
    }
}

//发送消息并储存消息到仓库和本地的方法
const sendMessage = async () => {
    reqmessage.receiver_id = messageStore.chattingFriend.userId
    reqmessage.conversation_id = messageStore.chattingFriend.conversation_id
    reqmessage.send_time = Date.now()
    try {
        const praseMessage = parseRichText(messageInput.value!)
        if (praseMessage.text) {
            reqmessage.message_type = 'text'
            reqmessage.message_content = praseMessage.text
            if (reqmessage.message_content.trim() === '') {
                return ElMessage({
                    type: 'warning',
                    message: '您的输入为空，请输入有效消息',
                })
            }
            //发送请求到后端，等待响应
            try {
                await handleFile()
            } catch (error) {
                ElMessage.error('消息发送失败，请稍后重试')
            }
        }
        if (praseMessage.images.length !== 0) {
            reqmessage.message_type = 'picture'
            reqmessage.message_content = '[图片]'
            for (let i = 0; i < praseMessage.images.length; i++) {
                reqmessage.media_url = `/chatAppServer/${reqmessage.message_type}/${praseMessage.images[i].fileName}`
                reqmessage.media = (praseMessage.images[i].fileData as string).split(',')[1]
                reqmessage.media_size = praseMessage.images[i].fileSize
                reqmessage.file_width = praseMessage.images[i].fileWidth
                reqmessage.file_height = praseMessage.images[i].fileHeight
                const picture = base64ToFile(
                    praseMessage.images[i].fileData as string,
                    praseMessage.images[i].fileName,
                )
                //发送请求到后端，等待响应
                try {
                    await handleFile(picture, praseMessage.images[i].fileName)
                } catch (error) {
                    ElMessage.error('消息发送失败，请稍后重试')
                }
            }
        }
    } catch (error) {
        return ElMessage({
            type: 'error',
            message: (error as Error).message,
        })
    }
    //将输入框清空
    messageInput.value!.textContent = ''
    reqmessage.message_type = ''
    reqmessage.message_content = ''
}

//监听路由变化
watch(
    () => $route.path,
    () => {
        if (messageInput.value) {
            messageInput.value.textContent = ''
        }
    },
    { deep: true },
)
</script>

<style lang="scss">
.el-popper.is-customized {
    padding: 2px 2px;
    background: linear-gradient(90deg, $system-default-theme-color, $system-default-theme-color);
    color: white;
}

.el-popper.is-customized .el-popper__arrow::before {
    background: linear-gradient(45deg, $system-default-theme-color, $system-default-theme-color);
    right: 0;
}
</style>

<style scoped lang="scss">
.bottomContent {
    height: 100%;
    @include flex-layout(flex, normal, normal, nowrap, column);
}

.functions {
    height: 2rem;
    padding: 0.2rem 1.5rem;
    @include flex-layout();

    .function {
        height: 1.8rem;
        margin-right: 1.5rem;

        :hover {
            cursor: pointer;
        }
    }
}

.messageInput {
    font-size: 1.2rem;
    width: 100%;
    flex: 1;
    padding: 0.2rem 1.5rem 0 1.5rem;
    box-shadow: none;
    border-radius: 0;
    overflow: auto;
    resize: none;
}

.buttonContainer {
    height: 2.5rem;
    margin-right: 1rem;
    @include flex-layout(flex, center, normal, nowrap, row-reverse);
}
</style>
